/* Copyright (c) 2021 Xie Meiyi(xiemeiyi@hust.edu.cn) and OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */

//
// Created by Wangyunlai on 2022/07/05.
//

#pragma once

#include <string.h>
#include "storage/common/field.h"
#include "sql/expr/tuple_cell.h"
#include "util/date.h"
#include "sql/expr/expression.h"

// 声明了一个Tuple类
class Tuple;

// ExprType有三种
// 分别是NONE，FIELD和VALUE
// 主要就是FIELD（字段类型）和VALUE（值类型）
enum class ExprType {
  NONE,
  FIELD,
  VALUE,
};

// 声明了一个表达式类
class Expression
{
public: 
  Expression() = default;
  virtual ~Expression() = default;
  
  // 获得一个值的函数
  // 这个在expression.cpp中
  virtual RC get_value(const Tuple &tuple, TupleCell &cell) const = 0;
  // 确定表达式类型的函数
  virtual ExprType type() const = 0;
};

// 声明了一个Expression的继承类FieldExpr
// 即字段表达式
class FieldExpr : public Expression
{
public:
  FieldExpr() = default;
  FieldExpr(const Table *table, const FieldMeta *field) : field_(table, field)
  {}

  virtual ~FieldExpr() = default;

  // 返回的是ExprType的FIELD
  // 重载的函数在上面43行
  ExprType type() const override
  {
    return ExprType::FIELD;
  }

  // 返回的是一个Field类型的类。即字段
  Field &field()
  {
    return field_;
  }

  // 调用这个函数能够获取到这个类当前的private成员Field field_
  const Field &field() const
  {
    return field_;
  }

// 返回了字段的表名
  const char *table_name() const
  {
    return field_.table_name();
  }

// 返回的是字段的字段名
  const char *field_name() const
  {
    return field_.field_name();
  }

  RC get_value(const Tuple &tuple, TupleCell &cell) const override;
private:
  Field field_;
};

// value是值表达式
// 这个就是Expression的第二个类，ValueExpr
class ValueExpr : public Expression
{
public:
  ValueExpr() = default;
  // 如果value的type是chars，则要捕捉一下这个char变量的长度
  ValueExpr(const Value &value) : tuple_cell_(value.type, (char *)value.data)
  {
    if (value.type == CHARS) {
      tuple_cell_.set_length(strlen((const char *)value.data));
    }
  }

  virtual ~ValueExpr() = default;

  // get_value相应的内容在expression.cpp中
  RC get_value(const Tuple &tuple, TupleCell & cell) const override;

  // 先把value的值字段void转化为字符串string类型
  // 再把string类型的字符串转化为date
  static RC value_string_to_date(const Value &value, std::string b, int32_t &date)
  {
    void *a = value.data;
    b = *(std::string*) a;
    const char *str = b.c_str();
    // b把value的data字段变成了string类型，然后我们调用一个函数来判断他是否是一个date类型的数据
    int year = 0;
    int month = 0;
    int day = 0;
    int ret = sscanf(str, "%d-%d-%d", &year, &month, &day);
    if (ret != 3){
        return RC::INVALID_ARGUMENT;
    }

    if (year < 1900 || year > 9999 || (month <= 0 || month > 12) || (day <= 0 || day > 31)){
        return RC::INVALID_ARGUMENT;
    }
    
    int max_day_in_month[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    const int max_day = max_day_in_month[month - 1];
    if (day > max_day){
        return RC::INVALID_ARGUMENT;
    }
    if (month == 2 && !is_leap_year(year) && day > 28){
        return RC::INVALID_ARGUMENT;
    }
    
    date = year * 10000 + month * 100 + day;
    return RC::SUCCESS;
  }

  // 调用这个函数能捕获到我们这个type是ExprType中的VALUE
  ExprType type() const override
  {
    return ExprType::VALUE;
  }

  // 调用这个函数能够获取到这个类的tuple_cell_
  // 并把这个tuple_cell_赋给函数的参数cell
  void get_tuple_cell(TupleCell &cell) const {
    cell = tuple_cell_;
  }

private:
  TupleCell tuple_cell_;
};
